module fft_core_control_unit
(
  //OUTPUTS
  output reg mem_src,
  output reg mem_rd_core,
  output reg mem_wr_core,
  output reg start_butt,
  output reg addr_unit_en,
  output reg config_src,
  output reg config_en,
  output reg int_set,
  output reg start_set,
  output busy_n,
  //INPUTS
  input addr_unit_rdy,
  input mem_rdy,
  input butt_rdy,
  input start,
  input clk,
  input rst_n
);

//=============================================================================
// 1)  Memory Banks: Data and Address Bus Mux source
//=============================================================================
localparam SRC_CORE = 1'b0;
localparam SRC_BUS  = 1'b1;

//=============================================================================
// 2)  Enables signals
//=============================================================================
localparam ENABLE  = 1'b1;
localparam DISABLE = 1'b0;

//=============================================================================
// 3)  REG_CONFIG source
//=============================================================================
localparam CONFIG_CORE = 1'b1;
localparam CONFIG_BUS  = 1'b0;

//=============================================================================
// 4)  FSM STATES
//=============================================================================
localparam IDLE      = 2'd0;
localparam READ_MEM  = 2'd1;
localparam BUTTERFLY = 2'd2;
localparam WRITE_MEM = 2'd3;

reg [1:0] state, next_state;

//State Memory
always @(posedge clk, negedge rst_n)
  begin
    if(!rst_n)
      begin
        state <= IDLE;
      end
    else
      begin
        state <= next_state;
      end
  end
  
//Next State Logic
always @(*)
  begin
    next_state = state;
    case(state)
      IDLE:
        begin
          next_state = (start) ? READ_MEM : IDLE;
        end
      READ_MEM:
        begin
          next_state = (mem_rdy) ? BUTTERFLY : READ_MEM;
        end
      BUTTERFLY:
        begin
          next_state = (butt_rdy) ? WRITE_MEM : BUTTERFLY;
        end
      WRITE_MEM:
        begin
          if(!mem_rdy)
            next_state = WRITE_MEM;
          else
            if(!addr_unit_rdy)
              next_state = READ_MEM;
            else
              next_state = IDLE;
        end
      //default:
    endcase
  end
  
//Output Logic 
assign busy_n = (state == IDLE);

always @(*)
  begin
    mem_src      = SRC_CORE;
    mem_rd_core  = DISABLE;
    start_butt   = DISABLE;
    addr_unit_en = DISABLE;
    config_src   = CONFIG_CORE;
    config_en    = DISABLE;
    int_set      = DISABLE;
    start_set    = DISABLE;
    mem_wr_core  = DISABLE;
    case(state)
      IDLE:
        begin
          mem_src = SRC_BUS;
          config_src = CONFIG_BUS;
        end
      READ_MEM:
        begin
          mem_src = SRC_CORE;
          mem_rd_core = ENABLE;
          start_butt = (mem_rdy) ? ENABLE : DISABLE;
        end
      WRITE_MEM:
        begin
          mem_src = SRC_CORE;
          mem_wr_core = ENABLE;
          addr_unit_en = (mem_rdy) ? ENABLE : DISABLE;
          if(mem_rdy && addr_unit_rdy)
            begin
              config_src = CONFIG_CORE;
              config_en = ENABLE;
              int_set = ENABLE;
              start_set = DISABLE;
            end
        end
      //default:
    endcase 
  end
  
endmodule
